package com.example.tkserver.utils.wxutil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.tomcat.util.codec.binary.Base64;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @Author: zp.wei
 * @DATE: 2020/7/7 14:47
 */
public class WXBizDataUtil {

    public static final String APPID = "wx6ed8404fdf69398a";

    public static String illegalAesKey = "-41001";//非法密钥
    public static String illegalIv = "-41002";//非法初始向量
    public static String illegalBuffer = "-41003";//非法密文
    public static String decodeBase64Error = "-41004"; //解码错误
    public static String noData = "-41005"; //数据不正确

    private String appid;

    private String sessionKey;

    public WXBizDataUtil(String appid, String sessionKey) {
        this.appid = appid;
        this.sessionKey = sessionKey;
    }

    /**
     * 检验数据的真实性，并且获取解密后的明文.
     *
     * @param encryptedData string 加密的用户数据
     * @param iv            string 与用户数据一同返回的初始向量
     * @return String 返回用户信息
     */
    public String decryptData(String encryptedData, String iv) {
        if (sessionKey.length() != 24) {
            return illegalAesKey;
        }
        // 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
        byte[] aesKey = Base64.decodeBase64(sessionKey);

        if (iv.length() != 24) {
            return illegalIv;
        }
        // 对称解密算法初始向量 为Base64_Decode(iv)，其中iv由数据接口返回。
        byte[] aesIV = Base64.decodeBase64(iv);

        // 对称解密的目标密文为 Base64_Decode(encryptedData)
        byte[] aesCipher = Base64.decodeBase64(encryptedData);
        try {
            byte[] resultByte = AESUtil.decrypt(aesCipher, aesKey, aesIV);
            if (null != resultByte && resultByte.length > 0) {
                String userInfo = new String(resultByte, "UTF-8");
                JSONObject jsons = JSON.parseObject(userInfo);
                JSONObject watermark =  jsons.getJSONObject("watermark");
                if (watermark != null){
                    String id = watermark.getString("appid");
                    if (id != null && !id.equals(appid)) {
                        return illegalBuffer;
                    }
                }
                return userInfo;
            } else {
                return noData;
            }
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 根据微信数据和sessionkey生成用于校验的签名
     *
     * rawData     微信数据
     * sessionKey  sessionkey
     */
    public static String getsignature2(String rawData, String sessionKey) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String stringASCII = rawData + sessionKey;
        String signature2 = null;
        try {
            //指定sha1算法
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(stringASCII.getBytes("UTF-8"));
            //获取字节数组
            byte messageDigest[] = digest.digest();
            // 创建 Hex 字符串
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
                signature2 = hexString.toString().toLowerCase();
            }
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            throw e;
        }
        return signature2;
    }

    public static JSONObject getUserInfo(String iv, String encryptedData, String sessionKey) {
        String userInfo = null;
        //解密数据
        try {
            WXBizDataUtil biz = new WXBizDataUtil(APPID, sessionKey);
            userInfo = biz.decryptData(encryptedData, iv);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return JSONObject.parseObject(userInfo);
    }

}
